#ifndef BUDDY_ALLOCATOR_H
#define BUDDY_ALLOCATOR_H

#include <List.h>

class Frame{
	public:
	uint32	_reserved;
	uint32	_flags;
	uint32	_order;
	uint32	_in_use;
	addr_t	_slab;		//адрес объекта Slab, если фрейм задействован распределителем участков
    Link	_frames;	//Поле для связи
    
	public:
		Frame():_reserved(0),_flags(0),_order(0),_in_use(0){}
		inline void setOrder(uint32 order){
			_order = order;
		}
		
		inline void setInUse(){
			_in_use = 1;		
		}
		
		inline void clrInUse(){
			_in_use = 0;
		}
		
		inline uint32 getOrder(){
			return _order;
		}
		
		inline uint32 isReserved(){
			return _reserved;
		}
		inline uint32 isFree(){
			return !_in_use;
		}
		inline void setSlab(addr_t slb){
			_slab = slb;
		}
		inline addr_t getSlab(){
			return _slab;
		}
};

extern Frame* mem_map;
//Количество очередей блоков кадров для buddy распределителя
#define FRM_MAX_ORDER	10
#define PAGE_SHIFT		12

#define _frm_to_addr(frm)	\
	((void *)(((frm) - mem_map) << PAGE_SHIFT))

#define _addr_to_frm(adr)	\
	(mem_map + ((uint32)(adr) >> PAGE_SHIFT))

#define _pa(addr)	\
	((void *)((addr_t)(addr) - 0xc0000000))

#define _va(addr)	\
	((void *)((uint32)(addr) + 0xc0000000))
	
/*Распределитель кадров физической памяти по методу близнецов*/
class BuddyFrameManager{
	Frame*	_frame_map;		//Адрес дескриптора первого кадра области, управляемой менеджером
	uint32	_first_frn;		//Номер первого кадра в области за которую отвечает менеджер
	uint32	_zone_size;		//Количество кадров в области, включая дыры (размер области)
	uint32	_free_frames;		//Количество свободных кадров в распоряжении менеджера
	List	_frm_lists[FRM_MAX_ORDER + 1];	//Массив списков свободных кадров
	public:
	BuddyFrameManager(Frame *start_frm, uint32 sz);
	
	void printManager();
	
	Frame * _allocFrames(uint32 flags, uint32 order);

	inline Frame * _allocFrame(uint32 flags){
		return _allocFrames(flags, 0);
	}

	inline void * allocFrames(uint32 flags, uint32 order){
		Frame *frm = _allocFrames(flags, order);
		return (void *)((frm - mem_map) << PAGE_SHIFT);
	}

	inline void * allocFrame(uint32 flags){
		return allocFrames(flags, 0);
	}
	
	void freeFrames(Frame *startFrame);

//	inline void freeFrames(void *addr);
	
	uint32 getFreeFrames();
	
	void * operator new(size_t sz, void *addr);
};

extern BuddyFrameManager *zone_normal;



#endif /* BUDDY_ALLOCATOR_H */

